package synchronicity.host;

import java.util.Vector;

import synchronicity.agent.Agent;
import synchronicity.calendar.Calendar;
import synchronicity.calendar.Calendar.ModifyCalendarFailedException;
import synchronicity.discovery.Discovery;
import synchronicity.util.Range;
import synchronicity.util.RangeSet;

/**
 * A basic implementation of a SchedulerHost that uses a depth-first
 * search for agent traversal.
 */
public class SchedulerHostImpl implements SchedulerHost {

	Vector listeners;

	Discovery discovery;

	Calendar calendar;

	String identifier;

	public SchedulerHostImpl(Calendar calendar, Discovery discovery) {
		listeners = new Vector();
		this.calendar = calendar;
		this.discovery = discovery;
	}

	public RangeSet getBusyTimes(Range range) {
		return calendar.getBusyTimes(range);
	}

	public void addMeeting(Range range, String title)
			throws ModifyCalendarFailedException {
		calendar.addCalendarItem(range, title);
		for (int ii = 0; ii < listeners.size(); ii++) {
			MeetingSchedulerListener listener = (MeetingSchedulerListener) listeners
					.elementAt(ii);
			listener.meetingScheduled(range, title);
		}
	}

	public SchedulerHost[] getHostsReachableFromHere() {
		return discovery.findOtherHosts();
	}

	public Agent traverse(Agent agent) {
		agent.visit(this);
		SchedulerHost[] otherHosts = getHostsReachableFromHere();
		for (int ii = 0; ii < otherHosts.length; ii++) {
			if (!alreadyVisitedHost(otherHosts[ii], agent)) {
				agent = otherHosts[ii].traverse(agent);
			}
		}
		return agent;
	}

	private boolean alreadyVisitedHost(SchedulerHost otherHost, Agent agent) {
		String[] hostsVisited = agent.getHostsVisited();
		boolean visited = false;
		for (int jj = 0; jj < hostsVisited.length; jj++) {
			if (otherHost.getHostIdentifier().equals(hostsVisited[jj]))
				visited = true;
		}
		return visited;
	}

	public String getHostIdentifier() {
		return identifier;
	}

	public void setHostIdentifier(String identifier) {
		this.identifier = identifier;
	}

	public void addMeetingSchedulerListener(MeetingSchedulerListener listener) {
		listeners.addElement(listener);
	}

	public void removeMeetingSchedulerListener(MeetingSchedulerListener listener) {
		listeners.removeElement(listener);
	}
	
	public Calendar getCalendar() {
		return this.calendar;
	}

}
